﻿Imports stigzler
Imports System.Reflection
Imports System.Collections.Generic
Imports System.Data
Imports System.IO
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Windows.Forms
Imports System.IO.File

Public Class GEmvoy

    Private _msg1 As String = ""
    Public Property Message1() As String
        Get
            Return _msg1
        End Get
        Set(ByVal value As String)
            _msg1 = value
        End Set
    End Property

    Private _msg2 As String = ""
    Public Property Message2() As String
        Get
            Return _msg2
        End Get
        Set(ByVal value As String)
            _msg2 = value
        End Set
    End Property

    'Public _gecamenabled As Boolean = False
    'Public Property GECamEnabled() As Boolean
    '    Get
    '        Return _gecamenabled
    '    End Get
    '    Set(ByVal value As Boolean)
    '        _gecamenabled = value
    '    End Set
    'End Property

    Private _gethememediapath As String
    Public Property GEThemeMediaPath() As String
        Get
            Return _gethememediapath
        End Get
        Set(ByVal value As String)
            _gethememediapath = value
        End Set
    End Property





    '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ' GLOBALS
    '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    'TESTS
    'Public emudt As New DataTable
    '/TESTS


    'OPERTIONAL
    Public Shared GameExPath As String
    Public Shared GECamEnabled As Boolean
    Public Shared Setts As New MySetts
    Public Shared db As New DebugConsole
    Public Shared log As New Logger

    Public Shared XMLFile As String
    Public Shared XMLOps As New XMLOps

    Public Shared Main As New MainProcess

    'TABLE IDs
    Public Shared SysSetupID As Integer
    Public Shared GExEmuID As Integer

    'EMU SELECTOR
    Public Shared SystemEmus As New SortedList(Of Integer, String)


    'BACKUP
    ' Public FileBackup As NumericFileRoller



    'Window Minimise
    'Const SW_HIDE As Integer = 0
    'Const SW_RESTORE As Integer = 1
    'Const SW_MINIMIZE As Integer = 2
    'Const SW_MAXIMIZE As Integer = 3
    'Private Function ShowWindow(ByVal hwnd As Integer, ByVal nCmdShow As Integer) As Integer
    'End Function


    'TOKENS
    'Public Shared Tokens As New Dictionary(Of String, String) From {{"[ROMPATH]", ""}, {"[ROMNAME]", ""},
    '                                                                {"[ROMUSED]", ""},
    '                                                                {"[QLAUNCHROOT]", ""}, {"[QLAUNCHGAME]", ""},
    '                                                                {"[VDRIVELTR]", ""}, {"[VDRIVETYPE]", ""},
    '                                                                {"[GESYSTEM]", ""}, {"[GEMSYSTEM]", ""},
    '                                                                {"[GEEMULATOR]", ""}, {"[GEMEMULATOR]", ""},
    '                                                                {"[GEGAMENAME]", ""}, {"[GEMGAMENAME}", ""},
    '                                                                {"[CATAGORY]", ""}, {"[YEAR]", ""},
    '                                                                {"[DEVELOPER]", ""}, {"[DESCRIPTION]", ""},
    '                                                                {"[SNAPPATH]", ""}, {"[TITLEPATH]", ""}}

    'CONSTANTS
    Public Shared FileExts As New List(Of String) From {"img", "mds", "ccd", "cue", "cdi", "gdi", "bin",
                                                        "smc", "sfc", "fig", "mdf", "iso"}
    Public Shared QlaunchPrompt As New List(Of String) From {"Keep", "Ask", "Delete"}
    Public Shared AlsoLaunch As New List(Of String) From {"Before", "After"}
    Public Shared DriveTypes As New List(Of String) From {"SCSI", "DT"}
    Public Shared AppVisibilities As New List(Of String) From {"Hidden", "Normal", "Minimized", "Maximized"}

    Public Shared SendKeysList As New Dictionary(Of String, String)



    '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ' /GLOBALS
    '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



    Public Function GetSystemEmus(GEEmuID As Integer, romname As String, rompath As String) As Boolean

        Try
            log.echo(">>> GetSystemEmus")
            log.echo("Passed GameEx EmuID: " & GEEmuID)
            log.echo("Passed romname: " & romname)
            log.echo("Passed rompath: " & rompath)

            Dim TempSysID As Integer
            Dim tempSysSetupID As Integer

            SystemEmus.Clear()
            SystemEmus.Add(-1, "Default Emulator")

            Dim selrow() As DataRow = GemDSM.Tables("UserEmulators").Select("UserEmuGEID = " & GEEmuID)
            Dim UserEmusID As Integer = selrow(0).Item("ID")
            Dim DefSysEmu As Integer = Nothing

            For Each row As DataRow In GemDSM.Tables("SystemsSetups").Rows
                'db.echo("processing SysSetups row: " & row.Item("Name"))
                'db.echo(row.Item("UserEmuID") & ", " & _geEmuID)
                If row.Item("UserEmuID") = UserEmusID Then
                    If row.Item("UseGEmvoy") = False Then
                        db.echo("Use GEmvoy set to false for this System. Return False.")
                        ' GameEx.Plugin.AltEmusForSystem = False
                        Return False
                    End If
                    db.echo("SysSetups row found: " & row.Item("Name"))
                    TempSysID = row.Item("SystemID")
                    tempSysSetupID = row.Item("ID")
                    DefSysEmu = row.Item("DefEmuSetupID")
                End If
            Next

            Dim emurow() As DataRow = Nothing
            For Each row As DataRow In GemDSM.Tables("EmuSetups").Rows
                If row.Item("SystemID") = TempSysID Then
                    emurow = GemDSM.Tables("EmulatorList").Select("ID = " & row.Item("EmuID"))
                    SystemEmus.Add(row.Item("ID"), emurow(0).Item("Name"))
                    If DefSysEmu = row.Item("ID") Then
                        SystemEmus(-1) = "Default Emulator"
                    End If
                End If
            Next

            ''Get default emu for GameProfile if exists:
            'log.echo("Determining correct ROM file from 'Rom': " & romname)
            'Dim FileLocation As DirectoryInfo = New DirectoryInfo(rompath)
            'Dim fi As FileInfo() = FileLocation.GetFiles(romname & ".*")
            '' db.echo("file 1: " & fi(0).Name)
            'If fi.Length > 0 Then
            '    Dim ROMFilename = fi(0).Name
            '    log.echo("File: " & MakeSQLSafe(ROMFilename))
            '    log.echo("SysSetupID: " & tempSysSetupID)

            '    Dim gamerow() As DataRow = GemDSM.Tables("Games").Select("SysSetupID = " & tempSysSetupID &
            '                                                             " AND RomFile = '" & MakeSQLSafe(ROMFilename) &
            '                                                             "' AND DefaultForGame = true")
            '    If gamerow.Length > 0 Then
            '        db.echo("Game matching System, romname and default for game found...")
            '        Dim emusetuprow() As DataRow = GemDSM.Tables("EmuSetups").Select("ID = " & gamerow(0).Item("EmuSetupID"))
            '        emurow = GemDSM.Tables("EmulatorList").Select("ID = " & emusetuprow(0).Item("EmuID"))
            '        db.echo("Def Emu name: " & emurow(0).Item("Name"))
            '        GameEx.Plugin.DefEmuForGame = emurow(0).Item("Name")
            '    Else
            '        db.echo("No games found - setting to 'none set'")
            '        GameEx.Plugin.DefEmuForGame = "None Set."
            '    End If
            'Else
            '    log.echo("No files of any extention matching that Romname")
            'End If

            Dim Current As KeyValuePair(Of Integer, String) = Nothing
            Dim CurrentEmuKey As Integer = -1
            Return True
        Catch ex As Exception
            db.echo("ERROR:")
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
            Return False
        End Try



        db.echo(">>> END GetSystemEmus")

    End Function

    Public Function MakeSQLSafe(ByVal sql As String) As String
        'first i'd avoid putting quote chars in as they might be valid? just double them up.
        Dim strIllegalChars As String = "/?-^%{}[];$=*`#|&@\<>()+,\"
        'replace single quotes with double so they don't cause escape character
        If sql.Contains("'") Then
            sql = sql.Replace("'", "''")
        End If
        Return sql
    End Function

    Private Sub GEmvoy_FormClosing(sender As Object, e As Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        'Save User Settings:
        Setts.SaveSetts()
        'Save Database:
        XMLOps.SaveXML(GemDSM, XMLFile)
    End Sub


    Public Sub GEmvoy_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    End Sub


    Public Shared Sub Test_Joy()

    End Sub

    Private Sub DBBackup()
        Dim DBBU As New BackupRoller
        With DBBU
            .BackupDirectory = Setts.DatabaseDir & "\User\DBBackup"
            .BackupFile = Setts.DatabaseDir & "\GemDS.xml"
            .KeepDays = New List(Of DayOfWeek) From {DayOfWeek.Saturday, DayOfWeek.Wednesday}
            .KeepDaysNumber = 2
            .KeepDates = New List(Of Day) From {14, 26}
            .KeepDatesNumber = 1
            .KeepTodayNumber = 10
            .KeepYesterday = True
            .YesterdayNumber = 5
            .Oldest = 6
            .Debug = db
        End With
        DBBU.Initialise()
        If DBBU.Backup() = False Then
            db.echo("Database backup failed")
        Else
            db.echo("Database backup routione completed successfully.")
        End If
    End Sub

    Private Sub IniBackup()
        Dim DBBU As New BackupRoller
        With DBBU
            .BackupDirectory = GameExPath & "\PLUGINS\GEmvoy\User\IniBackup"
            .BackupFile = GameExPath & "\PLUGINS\GEmvoy\settings.ini"
            .KeepDays = New List(Of DayOfWeek) From {DayOfWeek.Saturday}
            .KeepDaysNumber = 2
            .KeepDates = New List(Of Day) From {7}
            .KeepDatesNumber = 1
            .KeepTodayNumber = 5
            .KeepYesterday = True
            .YesterdayNumber = 3
            .Oldest = 6
            .Debug = db
        End With
        DBBU.Initialise()
        If DBBU.Backup() = False Then
            db.echo("Settings backup failed")
        Else
            db.echo("Settings backup routione completed successfully.")
        End If
    End Sub

    Private Sub KillHideOS()
        'kill any Backgrounds
        Dim bgProc() As Process = Process.GetProcessesByName("HideOS")
        For Each cpw As Process In bgProc
            cpw.Close()
        Next
    End Sub

    Private Sub DisableHideOS()
        If File.Exists(GameExPath & "\HideOS.exe") Then
            log.echo("Diasble HIdeOS Enabled in settings and HideOS.exe found in GE folder. Renaming to HideOS_BAK.exe and deleting original exe")
            KillHideOS()
            Try
                File.Copy(GameExPath & "\HideOS.exe", GameExPath & "\HideOS_BAK.exe")
                File.Delete(GameExPath & "\HideOS.exe")

            Catch ex As Exception
                log.echo("Error diabling HideOS: " & ex.Message)
            End Try
        End If
    End Sub

    Public Function InitialisePlugin(Optional SupressConsole = False) As Boolean

        'BEFORE ANYTHING - get GE path
        GetGEPath()
        'LOG
        log.Initialize("GEmvoy", GameEx.PluginInfo.Version, GameExPath & "\PLUGINS\GEmvoy\MainLog.txt",
                       False, False, db)
        log.echo("GEMVOY APP LOADED....")

        ''TEST -  KILL HIDE OS
        'KillHideOS()
        'DisableHideOS()

        'Write Changelog to user folder
        File.WriteAllText(Path.Combine(GameExPath & "\PLUGINS\GEmvoy\User", "ChangeLog.txt"), My.Resources.Changelog)


        'LOAD MY SETTINGS
        If File.Exists(GameExPath & "\PLUGINS\GEmvoy\settings.ini") Then
            IniBackup()
            log.echo("Settings ini backup completed. ")
        Else
            log.err("Settings file showing as not existing - using app defaults + writing new file. File: " & GameExPath & "\PLUGINS\GEmvoy\settings.ini")
            File.WriteAllText(Path.Combine(GameExPath & "\PLUGINS\GEmvoy", "settings.ini"), My.Resources.DefaultIni)
        End If
        Setts.IniPath = GameExPath & "\PLUGINS\GEmvoy\settings.ini"
        Setts.LoadSetts()

        'SET XML Path
        If Setts.DatabaseDir = "" Then Setts.DatabaseDir = GameExPath & "\PLUGINS\GEmvoy"
        If File.Exists(Setts.DatabaseDir & "\GemDS.xml") Then
            'DATABASE BACKUP
            DBBackup()
            log.echo("Database xml backup completed. ")
        Else
            log.err("Database file showing as not existing - using app defaults + writing new xml file. File:" & Setts.DatabaseDir & "\GemDS.xml")
            File.WriteAllText(Path.Combine(Setts.DatabaseDir, "GemDS.xml"), My.Resources.DefaultXML)
        End If
        XMLFile = Setts.DatabaseDir & "\GemDS.xml"

        'LOAD XML
        XMLOps.LoadXML(GemDSM, XMLFile)

        'CONSOLE
        If Setts.ShowDebug = True And SupressConsole = False Then
            db.Show()
            db.WindowTitle = "GEmvoy Debug Window"
            db.TimeStamp = True
            'db.TextColor = Color.LightBlue
            db.Show()
            db.echo("Starting Plugin Initialise ...", False, "Initialise")
        End If

        'LOG
        'reinitialise with any setts
        log.Initialize("GEmvoy", GameEx.PluginInfo.Version, GameExPath & "\PLUGINS\GEmvoy\MainLog.txt",
                       Setts.SysDetsInLog, Setts.LogToDebug, db)
        log.echo("GEMVOY APP LOADED....")

        log.echo("GameEx Path: " & GameExPath)
        log.echo("XML File: " & XMLFile)


        'OUTPUT Settings to Log:

        log.echo(".")
        log.echo("Settings at GEmvoy Load: ")
        For Each p As System.Reflection.PropertyInfo In Setts.GetType().GetProperties()
            If p.CanRead Then
                Try
                    log.echo(p.Name & " = " & p.GetValue(Setts, Nothing))
                Catch ex As Exception
                    'log.err(ex.Message)
                    'log.err(ex.StackTrace)
                End Try
            End If
        Next

        log.echo(".")

        'SETUP DATABASE:
        'Re-import + update Systems, Emulators and User Emulators
        ImportGEData()

        If GemDSM.Tables("UserEmulators").Rows.Count = 0 Then
            Return False
        End If

        log.echo("Theme Media folder: " & _gethememediapath)

        'Other DB population tasks:
        InitDBPop()

        'BACKUPS:
        log.echo("Making any backups of media files...")
        'Check backup of Startbak (theme) exists - if not, create
        If File.Exists(_gethememediapath & "\GEMVOYStartBak.png") Then
            log.echo("GEMVOYStartBak.png already exists. Restoring to default.")
            RestoreHome()
        Else
            log.echo("GEMVOYStartBak.png DOES NOT EXIST. Creating")
            Try
                File.Copy(_gethememediapath & "\StartBak.png", _gethememediapath & "\GEMVOYStartBak.png")
                File.Copy(_gethememediapath & "\StartBak.png", _gethememediapath & "\GEMVOYStartBakBU.png")
            Catch ex As Exception
                log.echo("ERROR: Could not copy file.")
                log.echo(ex.Message, True)
                log.echo(ex.StackTrace, True)
            End Try
        End If

        Try
            log.echo("Dialog stuff: " & _gethememediapath)
            Dim BUFiles As New Dictionary(Of String, String) From {{"dialog.png", "dialog_template.png"}}
            For Each BUFile As KeyValuePair(Of String, String) In BUFiles
                If Not File.Exists(_gethememediapath & "\" & BUFile.Value) Then
                    File.Copy(_gethememediapath & "\" & BUFile.Key, _gethememediapath & "\" & BUFile.Value, True)
                    log.echo(_gethememediapath & "\" & BUFile.Value & " didn't exist - created")
                Else
                    log.echo(_gethememediapath & "\" & BUFile.Value & " already exists")
                End If
            Next
        Catch ex As Exception
            log.echo("ERROR: Could not copy file.")
            log.echo(ex.Message, True)
            log.echo(ex.StackTrace, True)
        End Try

        XMLOps.SaveXML(GemDSM, XMLFile)

        Try
            'ANY RANDOMISE FUCTIONS
            If Setts.RndIntroPath = "Disabled" Then
                log.echo("Random Intro sounds disabled")
            Else
                log.echo("SOUNDS: Random Intro path exists: " & Setts.RndIntroPath)
                ReplaceSound("introsound", Setts.RndIntroPath)
            End If
        Catch ex As Exception
            db.echo("Error replacing intro sound - check folder path set...")
            log.echo(ex.Message, True)
            log.echo(ex.StackTrace, True)
        End Try

        ''Handle Unhandled exceptions
        '' Get the your application's application domain.
        'Dim currentDomain As AppDomain = AppDomain.CurrentDomain

        '' Define a handler for unhandled exceptions.
        'AddHandler currentDomain.UnhandledException, AddressOf MYExHandler

        '' Define a handler for unhandled exceptions for threads behind forms.
        'AddHandler Application.ThreadException, AddressOf MYThreadHandler

        'Dim X As Integer = 5
        'X = X / 0 'throws exception will be caught by subs below

        Return True

    End Function

    'Private Sub MYExHandler(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
    '    Dim EX As Exception

    '    EX = e.ExceptionObject
    '    MsgBox("Message: " & EX.Message & vbCr & "Stack:" & vbCr & EX.StackTrace & "Source: " & EX.Source, MsgBoxStyle.Critical, "Application Exception")
    'End Sub

    'Private Sub MYThreadHandler(ByVal sender As Object, ByVal e As Threading.ThreadExceptionEventArgs)
    '    MsgBox(e.Exception.StackTrace, MsgBoxStyle.Critical, "Thread exception")
    'End Sub

    Public Sub ReplaceSound(ByVal usefile As String, usefolderpath As String)

        Dim files() As String = getFiles(usefolderpath, "*.wav|*.mp3", SearchOption.TopDirectoryOnly)

        For Each foundfile As String In files
            db.echo(foundfile)
        Next

        Dim random As Random = New Random()

        Dim chosenfile = files(random.Next(0, files.Length - 1))

        db.echo("CHOSEN FILE: " & chosenfile)

        File.Delete(GEThemeMediaPath & "\" & usefile & ".wav")
        File.Delete(GEThemeMediaPath & "\" & usefile & ".mp3")

        File.Copy(chosenfile, GEThemeMediaPath & "\" & usefile & Path.GetExtension(chosenfile), True)

    End Sub

    ''' <summary>
    ''' Returns file names from given folder that comply to given filters
    ''' </summary>
    ''' <param name="SourceFolder">Folder with files to retrieve</param>
    ''' <param name="Filter">Multiple file filters separated by | character</param>
    ''' <param name="searchOption">File.IO.SearchOption, 
    ''' could be AllDirectories or TopDirectoryOnly</param>
    ''' <returns>Array of FileInfo objects that presents collection of file names that 
    ''' meet given filter</returns>
    Public Function getFiles(ByVal SourceFolder As String, ByVal Filter As String, _
     ByVal searchOption As System.IO.SearchOption) As String()
        ' ArrayList will hold all file names
        Dim alFiles As ArrayList = New ArrayList()

        ' Create an array of filter string
        Dim MultipleFilters() As String = Filter.Split("|")

        ' for each filter find mathing file names
        For Each FileFilter As String In MultipleFilters
            ' add found file names to array list
            alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption))
        Next

        ' returns string array of relevant file names
        Return alFiles.ToArray(Type.GetType("System.String"))
    End Function



    Public Sub QuickSaveXML()
        XMLOps.SaveXML(GemDSM, XMLFile)
    End Sub


    Public Sub TransposeImage()
        Dim BG As Image = Nothing
        Dim Perc As Integer = 8

        BG = SafeImageFromFile(_gethememediapath & "\StartBak.png")

        ' Dim ScaleFactor As Double = (BG.Size.Width - (BG.Size.Width * Perc / 100)) / BG.Size.Width
        ' Dim Leftpoint As Integer = BG.Width - CInt(BG.Width * Perc / 100) - 10
        Dim Leftpoint As Integer = 10

        Dim g As Graphics = Graphics.FromImage(BG)
        g.DrawImage(My.Resources.webcam, Leftpoint, 10,
                    CInt(BG.Width * Perc / 100),
                    CInt(BG.Height * Perc / 100))

        BG.Save(_gethememediapath & "\StartBak.png", Imaging.ImageFormat.Png)

    End Sub

    Public Shared Function SafeImageFromFile(path As String) As Image
        Using fs As New FileStream(path, FileMode.Open, FileAccess.Read)
            Dim img = Image.FromStream(fs)
            Return img
        End Using
    End Function

    Public Sub RestoreHome()

        File.Copy(_gethememediapath & "\GEMVOYStartBak.png", _gethememediapath & "\StartBak.png", True)
    End Sub

    Private Sub PopulateSendKeys()
        Dim sr As New StreamReader(GameExPath & "\PLUGINS\GEmvoy\Assets\SendKeys.ini")
        ' Dim openWith As New Dictionary(Of String, String)

        Do While sr.Peek <> -1
            Dim line As String() = sr.ReadLine().Split("|")
            SendKeysList.Add(line(0), line(1))
        Loop
    End Sub

    Public Sub InitDBPop()

        Dim nrow As DataRow

        'Other db population tasks on plugin initialisation:

        'Populate default File Extentions:
        Dim newrow As DataRow = Nothing
        For Each ext As String In FileExts
            If Not CheckValue(GemDSM.Tables("FileExts"), "Ext", ext) Then
                newrow = GemDSM.Tables("FileExts").NewRow
                db.echo(ext, False, "Extention Added")
                newrow.Item("Ext") = ext
                GemDSM.Tables("FileExts").Rows.Add(newrow)
            Else
                db.echo("Extemtion already in db: " & ext)
            End If
        Next

        'Update System_Setups from GEEmus table:
        db.echo("", False, "Updating GEEmus and SystemsSetup")

        Try
            'First setup or all systems deleted....

            For Each row As DataRow In GemDSM.Tables("UserEmulators").Rows
                db.echo("Processing UserEmus: " & row.Item("ID") & ". " & row.Item("StartPageName").ToString)
                'db.echo(row.Item("StartPageName") & " **** " & row.Item("TitleText"))
                newrow = GemDSM.Tables("SystemsSetups").NewRow
                If GemDSM.Tables("SystemsSetups").Select("UserEmuID = " & row.Item("ID")).Length = 0 Then
                    'Add New if non existing SystemSetup for this GEEmu
                    newrow.Item("UserEmuID") = row.Item("ID")
                    newrow.Item("Name") = NotNull(row.Item("StartPageName"), "StartPageName null in GameEx")
                    newrow.Item("RomsFolder") = NotNull(row.Item("RomPath"), "C:")
                    newrow.Item("UseGEmvoy") = False
                    GemDSM.Tables("SystemsSetups").Rows.Add(newrow)
                End If
            Next

            For i As Integer = 0 To GemDSM.Tables("SystemsSetups").Rows.Count - 1
                If GemDSM.Tables("UserEmulators").Select("ID = " &
                                    GemDSM.Tables("SystemsSetups").Rows(i).Item("UserEmuID")).Length = 0 Then
                    GemDSM.Tables("SystemsSetups").Rows(i).Delete()
                End If
            Next

        Catch ex As Exception
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try




        'Check Emu Setups for at least one record. If not - populate default
        If GemDSM.Tables("EmuSetups").Rows.Count = 0 Then
            newrow = GemDSM.Tables("EmuSetups").NewRow
            newrow("Name") = "Default Emu Setup - Please change"
            newrow("EmuID") = 0
            newrow("SystemID") = 0
            GemDSM.Tables("EmuSetups").Rows.Add(newrow)
        End If

        'Check Keys has Tab in it
        Dim srow() As DataRow = GemDSM.Tables("Keys").Select("WinKeyCode = 9")
        If srow.Length = 0 Then
            nrow = GemDSM.Tables("Keys").NewRow
            nrow("WinKeyCode") = 9
            nrow("WinEnumName") = "Tab"
            nrow("FriendlyName") = "Tab"
            nrow("VkeyCode") = 0
            GemDSM.Tables("Keys").Rows.Add(nrow)
        End If


        'Check EmuSettsProfile has "Default" for each Emulator + Game
        Try
            Dim match As Boolean

            For Each row As DataRow In GemDSM.Tables("EmuSetups").Rows
                match = False
                nrow = GemDSM.Tables("EmuSettsProfile").NewRow
                For Each crow As DataRow In GemDSM.Tables("EmuSettsProfile").Rows
                    If row("ID") = NotNull(crow("EmuSetupID"), -1) And crow("Name") = "Emulator Default" Then match = True
                    Continue For
                Next
                If match = False Then
                    nrow("Name") = "Emulator Default"
                    nrow("EmuSetupID") = row("ID")
                    GemDSM.Tables("EmuSettsProfile").Rows.Add(nrow)
                End If
            Next

            For Each row As DataRow In GemDSM.Tables("Games").Rows
                match = False
                nrow = GemDSM.Tables("EmuSettsProfile").NewRow
                For Each crow As DataRow In GemDSM.Tables("EmuSettsProfile").Rows
                    If row("ID") = NotNull(crow("GameID"), -1) And crow("Name") = "Game Default" Then match = True
                    Continue For
                Next
                If match = False Then
                    nrow("Name") = "Game Default"
                    nrow("GameID") = row("ID")
                    GemDSM.Tables("EmuSettsProfile").Rows.Add(nrow)
                End If
            Next

        Catch ex As Exception
            MsgBox(ex.Message & vbCr & ex.StackTrace)
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try

    End Sub

    Public Sub GetGEPath()

        Dim InitialSetup As New ReadGEInfo
        'GEPath
        db.echo(InitialSetup.GameExPath(), False, "GEPath")
        GameExPath = InitialSetup.GameExPath()

    End Sub

    Private Sub ImportGEData()

        Dim InitialSetup As New ReadGEInfo
        InitialSetup.GEPath = GameExPath

        Dim newrow As DataRow

        'Get GE Theme path
        _gethememediapath = GameExPath & InitialSetup.GameExThemeMediaPath

        'GE Emulators List
        Try
            For Each emu As String In InitialSetup.GEEmuList()
                If Not CheckValue(GemDSM.Tables("EmulatorList"), "Name", emu) Then
                    newrow = GemDSM.Tables("EmulatorList").NewRow
                    db.echo(emu, False, "Emu Added")
                    newrow.Item("Name") = emu
                    GemDSM.Tables("EmulatorList").Rows.Add(newrow)
                Else
                    db.echo("Emu already in db: " & emu)
                End If

            Next
        Catch ex As Exception
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try

        'GE Systems List
        Try
            For Each sys As String In InitialSetup.GESysList()
                If Not CheckValue(GemDSM.Tables("SystemsList"), "Name", sys) Then
                    newrow = GemDSM.Tables("SystemsList").NewRow
                    db.echo(sys, False, "Sys Added")
                    newrow.Item("Name") = sys
                    GemDSM.Tables("SystemsList").Rows.Add(newrow)
                Else
                    db.echo("Sys already in db: " & sys)
                End If
            Next
        Catch ex As Exception
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try

        'GE UserEmulators Table
        db.echo("", False, "Processing GE Emus")
        ' GemDSM.Tables("UserEmulators").Clear()

        Dim compareRow() As DataRow
        Dim importedrows As DataTable
        importedrows = InitialSetup.GEUserEmus()
        Try
            For Each row As DataRow In importedrows.Rows

                db.echo("Processing GE Emu: " & row.Item("EmuNumber") & ". " & row.Item("StartPageName").ToString)
                db.echo(row.Item("StartPageName") & " **** " & row.Item("TitleText"))
                newrow = GemDSM.Tables("UserEmulators").NewRow
                newrow.Item("UserEmuGEID") = NotNull(row.Item("EmuNumber"), 0)
                newrow.Item("StartPageName") = NotNull(row.Item("StartPageName").ToString, "<null>")
                newrow.Item("TitleText") = NotNull(row.Item("TitleText").ToString, "<null>")
                newrow.Item("SnapPath") = NotNull(row.Item("SnapPath"), "<null>")
                newrow.Item("TitlePath") = NotNull(row.Item("TitlePath"), "<null>")
                newrow.Item("Database") = NotNull(row.Item("Database"), "<null>")
                newrow.Item("Enabled") = NotNull(row.Item("Enabled"), "<null>")
                newrow.Item("RomPath") = NotNull(row.Item("RomPath"), "<null>")
                'IF UPDATE ABOVE REMEBER TO UPDATE READGEINFO.GEUserEmus too
                'newrow.Item("SnapPath") = "kjhkjh"
                'newrow.Item("TitlePath") = "kjhkjhkjh"

                If Not CheckValue(GemDSM.Tables("UserEmulators"), "UserEmuGEID", row.Item("EmuNumber")) Then
                    'NoGE EmuID existing in database - add new
                    db.echo("GEEmuID does not exist in db. Adding...")
                    GemDSM.Tables("UserEmulators").Rows.Add(newrow)
                Else
                    'GEEmuID of this number exists in db - Update
                    db.echo("GEEmuID already exists in db. Updating...")
                    compareRow = GemDSM.Tables("UserEmulators").Select("UserEmuGEID = '" & row.Item("EmuNumber") & "'")

                    If compareRow(0)("StartPageName") <> row.Item("StartPageName") Then
                        MsgBox("The StartPageName has changed for this GameEx Emulator from """ &
                        compareRow(0)("StartPageName").ToString & """ to """ & row("StartPageName") &
                        """ This can occur if you move Emulators up and down in the GameEx Setup Wizard or " &
                        "if you change the field in the Emulator setup. If a result of moving, you will have " &
                        "changed the GameEx emulator number for the System. You'll have to change the System setup " &
                        "in GEmvoy to re-align any existing setups for this system. See documentaion for more info." &
                        vbCr & vbCr & "In short: make sure you change the 'GEx Emulator' Dropdown in System Setups tab " &
                        "to make sure you match the GameEx system to the GEmvoy setup",
                        MsgBoxStyle.Exclamation, "Important - Requires Attention and Action")
                    End If

                    Dim CRowID As Integer = compareRow(0).Item("ID")
                    compareRow(0).Item("UserEmuGEID") = newrow.Item("UserEmuGEID")
                    compareRow(0).Item("StartPageName") = newrow.Item("StartPageName")
                    compareRow(0).Item("TitleText") = newrow.Item("TitleText")
                    compareRow(0).Item("SnapPath") = newrow.Item("SnapPath")
                    compareRow(0).Item("TitlePath") = newrow.Item("TitlePath")
                    compareRow(0).Item("Database") = newrow.Item("Database")
                    compareRow(0).Item("Enabled") = newrow.Item("Enabled")
                    compareRow(0).Item("RomPath") = newrow.Item("RomPath")
                End If

                '   GemDSM.Tables("EmulatorList").Rows.Add(r) 
            Next

            'NOw remove any GEUserEmus from Gemvoy table wghich no longer exist in GameEx(i.e. user deleted)
            Dim testrow() As DataRow
            For i As Integer = 0 To GemDSM.Tables("UserEmulators").Rows.Count - 1
                testrow = importedrows.Select("EmuNumber = " & GemDSM.Tables("UserEmulators").Rows(i).Item("UserEmuGEID"))
                If testrow.Length = 0 Then
                    GemDSM.Tables("UserEmulators").Rows(i).Delete()
                    Dim SysSetupRow() As DataRow
                    SysSetupRow = GemDSM.Tables("UserEmulators").Select("UserEmuID = " &
                                        GemDSM.Tables("UserEmulators").Rows(i).Item("ID"))
                    For z As Integer = 0 To SysSetupRow.Length - 1
                        SysSetupRow(z).Delete()
                    Next
                End If

            Next
        Catch ex As Exception
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try
        ' MsgBox("pause")

        db.echo("madeit!")

    End Sub

    Public Shared Function NotNull(Of T)(ByVal Value As T, ByVal DefaultValue As T) As T

        If Value Is Nothing OrElse IsDBNull(Value) Then
            Return DefaultValue
        Else
            Return Value
        End If
    End Function

    Shared Function CheckValue(myTable As DataTable, columnName As String, searchValue As String) As Boolean
        For Each row As DataRow In myTable.Rows
            If row(columnName) = searchValue Then Return True
        Next
        Return False
    End Function


    Private Sub Button1_Click(sender As Object, e As EventArgs)
        db.echo("XML Write:")
        db.echo("XMLFile: " & XMLFile)
        Try
            XMLOps.SaveXML(GemDSM, XMLFile)
        Catch ex As Exception
            db.echo(ex.Message, True)
            db.echo(ex.StackTrace, True)
        End Try
    End Sub

    Public Sub GameRun(Gameinfo As GameEx.Plugin.Game_Info)


        'TEST HIDE KILL OS
        'KillHideOS()

        'Minimise GameEx
        'Dim GEProc As Process() = Process.GetProcessesByName("gameex")
        'For Each proc As Process In GEProc
        '    db.echo(proc.MainWindowTitle, False, "Win: ")
        '    Dim hWnd As Integer = CType(proc.MainWindowHandle, Integer)
        '    ShowWindow(hWnd, SW_MINIMIZE)
        'Next
        Main = New MainProcess()

        'Pop vars
        Main.GEEmuID = Gameinfo.EmulatorNumber
        Main.RomName = Gameinfo.GameData.Description
        Main.GameInfo = Gameinfo
        Main.GameBio = GameEx.Plugin.GameBio
        Main.DataSet = GemDSM
        Main.DebugConsole = db
        Main.Log = log
        Main.FullBoot = True  ' put false here in config for setup boot
        Main.SkipClose = False
        Main.SpecdEmuSetupID = GameEx.Plugin.CurrentEmuKey
        Main.UseSpecificEmu = GameEx.Plugin.AltEmusForSystem

        'Main.MinimiseGameEx()

        Main.Initialise()

        'Main.SendAltEnter()

        ' Main.SendWinD() 'EDIT!!!!

        ' Main.MinimiseGameEx()
        Try
            Main.ProcessInput()
        Catch ex As Exception
            log.echo(ex.Message, True)
            log.echo(ex.StackTrace, True)
        End Try

    End Sub

    'Public Sub GameRunFromConfig(GEEmuID As Integer, RomName As String, ds As DataSet, db As DebugConsole, log As DracLabs.Logger, boot As Boolean)

    '    'Minimise GameEx
    '    'Dim GEProc As Process() = Process.GetProcessesByName("gameex")
    '    'For Each proc As Process In GEProc
    '    '    db.echo(proc.MainWindowTitle, False, "Win: ")
    '    '    Dim hWnd As Integer = CType(proc.MainWindowHandle, Integer)
    '    '    ShowWindow(hWnd, SW_MINIMIZE)
    '    'Next

    '    'Pop vars
    '    Main.GEEmuID = GEEmuID
    '    Main.RomName = RomName
    '    '    Main.GameInfo = Gameinfo
    '    '  Main.GameBio = GameEx.Plugin.GameBio
    '    Main.DataSet = ds
    '    Main.DebugConsole = db
    '    Main.Log = log
    '    Main.BootCmd = boot  ' put false here in config for setup boot

    '    Main.Initialise()
    '    Main.ProcessInput()

    'End Sub



    Public Sub GameExit()

        If Main.SkipClose = False Then
            db.echo("GEmvoy.GameExit reached. Running close routines")
            Main.AfterGameQuit()
        Else
            db.echo("GEmvoy.GameExit reached, but skipclose set to true (must be gemvoy not enabled for this system).")
        End If

        If db.WindowState = FormWindowState.Minimized Then
            db.WindowState = FormWindowState.Normal
        End If

        'Save any changes
        XMLOps.SaveXML(GemDSM, XMLFile)

    End Sub

    Public Sub ChangeMsg(msg As String, msgno As Integer)
        If msgno = 1 Then
            '  Msg1LB.Text = msg
            _msg1 = msg
        ElseIf msgno = 2 Then
            Msg2LB.Text = msg
            _msg2 = msg
        End If
        Me.Refresh()
    End Sub

    Private Sub GEmvoy_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        'Msg1LB.Text = _msg1
    End Sub

    Public Function ReturnCmdLine() As String
        db.echo("ReturnCmdLine called. Returning: " & Main.CmdLine)
        Return Main.CmdLine
    End Function

    Public Sub WriteGVEntry(entry As String, Optional console As Boolean = True, Optional tolog As Boolean = True)
        If console = True Then
            db.echo(entry)
        End If
        If tolog = True Then
            log.echo(entry)
        End If

    End Sub

End Class